package cnsatmsmart.automation.mmi.view.layers;

import cnsatmsmart.automation.mmi.helper.utilities.GlobalEnvVars;
import com.bbn.openmap.Layer;
import com.bbn.openmap.event.ProjectionEvent;
import com.bbn.openmap.omGraphics.OMGraphicList;
import com.bbn.openmap.proj.Projection;
import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import cnsatmsmart.automation.mmi.model.data.TSafe.Fix;
import cnsatmsmart.automation.mmi.model.database.DataBase;
import cnsatmsmart.automation.mmi.model.layers.OMLabelRectangle;
import cnsatmsmart.automation.mmi.model.layers.OMLabelTriangle;

/**
 * @author SIK - PTIK, BPPT
 **/

public class FixesLayer extends Layer {
    /* const */
        private static final int NAVAIDS_SIZE = 8;
            //nilai default untuk ukuran navaid pada penggambaran fix yang merupakan instance dari kelas FixesLayer

        private static final Color FIXES_COLOR = new Color (192, 192, 192);
            //nilai warna default untuk pewarnaan pada penggambaran fix yang merupakan instance dari kelas FixesLayer

    /* atribut - atribut yang dimiliki oleh kelas FixesLayer */
        private OMGraphicList graphics = new OMGraphicList();
        private Projection projection = null;

        private List < Fix > fixes = null;
        private List < Fix > navaids = null;

        boolean isCreated = false;
        
        private static String db_Connection = "jdbc:mysql:///MMI?user=" + GlobalEnvVars.db_Username + "&password=" + GlobalEnvVars.db_Password;
    
    /* constructor - user defined ctor, no default ctor */
        // <editor-fold defaultstate="collapsed" desc="ctor">
        /**
         * menginstansiasi object FixesLayer<br />
         * #do nothing ctor
         */
        public FixesLayer() { }
        // </editor-fold>

    /* getter */
        /**
         * melakukan retrieve basis data untuk mendapatkan List < Fix >
         * @return List < Fix > yang merupakan senarai fixes seperti yang terdapat pada basis data tabel fixes
         */
        public static List < Fix > getFixes() {
            List < Fix > RetVal = new ArrayList < Fix >();

            try {
                DataBase db = new DataBase(db_Connection);
                db.createQuery("SELECT * FROM fixes");

                while (db.getResultSet().next()) {
                    Fix f = new Fix(
                            db.getResultSet().getString("ID_Fixes"),
                            ((db.getResultSet().getFloat("Lat_Deg") + (db.getResultSet().getFloat("Lat_Min") / 60.0f) + (db.getResultSet().getFloat("Lat_Sec") / 3600.0f)) * (db.getResultSet().getString("Lat_Sign").equals("N") ? 1.0f : -1.0f)),
                            ((db.getResultSet().getFloat("Lon_Deg") + (db.getResultSet().getFloat("Lon_Min") / 60.0f) + (db.getResultSet().getFloat("Lon_Sec") / 3600.0f)) * (db.getResultSet().getString("Lon_Sign").equals("E") ? 1.0f : -1.0f))
                            );
                    RetVal.add(f);
                }
            } catch (Exception e) {
                System.out.println("failed to connect to database");
            }

            return (RetVal);
        }
        /**
         * melakukan retrieve basis data untuk mendapatkan List < Fix >
         * @return List < Fix > yang merupakan senarai fixes seperti yang terdapat pada basis data tabel airports
         */
        public static List < Fix > getAirports() {
            List < Fix > RetVal = new ArrayList < Fix >();

            try {
                DataBase db = new DataBase(db_Connection);
                db.createQuery("SELECT * FROM airports");

                while (db.getResultSet().next()) {
                    Fix f = new Fix(
                            db.getResultSet().getString("ID_Airports"),
                            ((db.getResultSet().getFloat("Lat_Deg") + (db.getResultSet().getFloat("Lat_Min") / 60.0f) + (db.getResultSet().getFloat("Lat_Sec") / 3600.0f)) * (db.getResultSet().getString("Lat_Sign").equals("N") ? 1.0f : -1.0f)),
                            ((db.getResultSet().getFloat("Lon_Deg") + (db.getResultSet().getFloat("Lon_Min") / 60.0f) + (db.getResultSet().getFloat("Lon_Sec") / 3600.0f)) * (db.getResultSet().getString("Lon_Sign").equals("E") ? 1.0f : -1.0f))
                            );
                    RetVal.add(f);
                }
            } catch (Exception e) {
                System.out.println("failed to connect to database");
            }

            return (RetVal);
        }
        /**
         * melakukan retrieve basis data untuk mendapatkan List < Fix >
         * @return List < Fix > yang merupakan senarai fixes seperti yang terdapat pada basis data tabel navaids
         */
        public static List < Fix > getNavaids() {
            List < Fix > RetVal = new ArrayList < Fix >();

            try {
                DataBase db = new DataBase(db_Connection);
                db.createQuery("SELECT * FROM navaids");

                while (db.getResultSet().next()) {
                    Fix f = new Fix(
                            db.getResultSet().getString("ID_Navaids"),
                            ((db.getResultSet().getFloat("Lat_Deg") + (db.getResultSet().getFloat("Lat_Min") / 60.0f) + (db.getResultSet().getFloat("Lat_Sec") / 3600.0f)) * (db.getResultSet().getString("Lat_Sign").equals("N") ? 1.0f : -1.0f)),
                            ((db.getResultSet().getFloat("Lon_Deg") + (db.getResultSet().getFloat("Lon_Min") / 60.0f) + (db.getResultSet().getFloat("Lon_Sec") / 3600.0f)) * (db.getResultSet().getString("Lon_Sign").equals("E") ? 1.0f : -1.0f))
                            );
                    RetVal.add(f);
                }
            } catch (Exception e) {
                System.out.println("failed to connect to database");
            }

            return (RetVal);
        }

    /* setter */
        /**
         * mengupdate graphics dari layer tanpa melakukan retrieve basis data jika sudah pernah dilakukan sebelumnya
         * @param graphics OMGraphicList yang merupakan container untuk menampung graphic yang akan diproyeksikan ke layar
         * @return OMGraphicList yang mengacu kepada graphics
         */
        public OMGraphicList setFixes(OMGraphicList graphics) {
            return (setFixes(graphics, false, false));
        }
        /**
         * mengupdate graphics dari layer
         * @param graphics OMGraphicList yang merupakan container untuk menampung graphic yang akan diproyeksikan ke layar
         * @param updateFixes boolean yang menentukan apakah pengupdatean tampilan didahului dengan proses retrieve basis data fixes sebelumnya atau tidak :<br />
         *                    bernilai true jika melakukan retrieve basis data dan false jika sebaliknya
         * @param updateNavaids boolean yang menentukan apakah pengupdatean tampilan didahului dengan proses retrieve basis data navaids sebelumnya atau tidak :<br />
         *                      bernilai true jika melakukan retrieve basis data dan false jika sebaliknya
         * @return OMGraphicList yang mengacu kepada graphics
         */
        public OMGraphicList setFixes(OMGraphicList graphics, boolean updateFixes, boolean updateNavaids) {
            graphics.clear();

            if ((this.fixes == null) || (updateFixes)) {
                this.fixes = getFixes();
            }

            if ((this.navaids == null) || (updateNavaids)) {
                this.navaids = getNavaids();
            }

            //FIXES
            if (this.fixes != null) {
                Iterator < Fix > fixesIter = this.fixes.iterator();
                while (fixesIter.hasNext()) {
                    Fix fix = fixesIter.next();
                    OMLabelTriangle point = new OMLabelTriangle((float)fix.getLatitude(), (float)fix.getLongitude(), fix.getID());
                    graphics.addOMGraphic(point);
                }
            }

            //NAVAIDS
            if (this.navaids != null) {
                Iterator < Fix > navaidsIter = this.navaids.iterator();
                while (navaidsIter.hasNext()) {
                    Fix navaid = navaidsIter.next();
                    OMLabelRectangle point = new OMLabelRectangle((float)navaid.getLatitude(), (float)navaid.getLongitude(), NAVAIDS_SIZE, navaid.getID());
                    point.setLinePaint(FIXES_COLOR);
                    graphics.addOMGraphic(point);
                }
            }

            isCreated = true;

            return (graphics);
        }

    /* method - method yang dimiliki oleh kelas FixesLayer */
        /**
         * mengupdate layer sesuai dengan data yang terdapat pada basis data yang terakhir diretrieve
         */
        public void update() {
            update(true, true);
        }
        /**
         * mengupdate layer sesuai dengan data yang terdapat pada basis data
         * @param updateFixes boolean yang menentukan apakah pengupdatean tampilan didahului dengan proses retrieve basis data fixes sebelumnya atau tidak :<br />
         *                    bernilai true jika melakukan retrieve basis data dan false jika sebaliknya
         * @param updateNavaids boolean yang menentukan apakah pengupdatean tampilan didahului dengan proses retrieve basis data navaids sebelumnya atau tidak :<br />
         *                      bernilai true jika melakukan retrieve basis data dan false jika sebaliknya
         */
        public void update(boolean updateFixes, boolean updateNavaids) {
            setFixes(this.graphics, updateFixes, updateNavaids);
            this.graphics.project(this.projection, true);
            repaint();
        }

    /**
     * event handler untuk event perubahan projection
     * @param pe ProjectionEvent event projection yang terjadi
     */
    public void projectionChanged(ProjectionEvent pe) {
        this.projection = (Projection) pe.getProjection().makeClone();
        if (! isCreated) {
            setFixes(this.graphics);
        }
        this.graphics.project(this.projection, true);
        repaint();
    }

    @Override
    public void paint (Graphics g) {
        this.graphics.render(g);
    }
}
